﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;

namespace Sharepoint.ExportList
{
    public partial class Main : Form
    {
        private static string _siteUrl = string.Empty;
        private static string _webRelativeUrl = string.Empty;
        private static string _selectedListName = string.Empty;



        private static bool _isFirstFilterSet;
        private static bool _isSecondFilterSet;
        private static string _filterOneFieldName = string.Empty;
        private static string _filterOneOp = string.Empty;
        private static string _filterOneValue = string.Empty;
        private static string _filterTwoFieldName = string.Empty;
        private static  string _filterTwoOp = string.Empty;
        private static string _filterTwoValue = string.Empty;
        private static string _filtersCondition = string.Empty;
        private static string _sortField = string.Empty;
        private static bool _ascending = true; 


        public Main()
        {
            InitializeComponent();
        }

        private void textBox2_MouseClick(object sender, MouseEventArgs e)
        {

        }

        private void textBox2_Click(object sender, EventArgs e)
        {
            DialogResult result = folderBrowserDialog1.ShowDialog();
            txtLocation.Text = folderBrowserDialog1.SelectedPath;
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            lblMessage.Text = "";
            LoadSiteLists();
        }

        private void LoadSiteLists()
        {
            string url = txtWebUrl.Text.Trim();
            _siteUrl = GetSiteUrl(url);
            _webRelativeUrl = url.Substring(_siteUrl.Length).Trim().Trim('/');

            try
            {
                using (var site = new SPSite(_siteUrl))
                {
                    using (SPWeb web = site.OpenWeb(_webRelativeUrl))
                    {
                        SPListCollection list = web.Lists;
                        listBoxSPLists.Items.Clear();
                        foreach (SPList spList in list)
                        {
                            listBoxSPLists.Items.Add(spList.Title);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                lblMessage.Text = "Error: Loading Site Error. Check Site Url";
            }
        }

        private string GetSiteUrl(string url)
        {
            if(!SPSite.Exists(new Uri(url)))
            {
                return GetSiteUrl(url.Substring(0, url.LastIndexOf('/')));
            }
            return url;
        }

        private void listBoxSPLists_SelectedIndexChanged(object sender, EventArgs e)
        {
            string selected = listBoxSPLists.SelectedItem.ToString();
            _selectedListName = selected;
            LoadProperties(selected);
        }

        private void LoadProperties(string selected)
        {
                        
            using (SPSite site = new SPSite(_siteUrl))
            {
                using (SPWeb web = site.OpenWeb(_webRelativeUrl))
                {
                    SPList list = web.Lists[selected];
                    checkedListBoxFields.Items.Clear();
                    filter1Field.Items.Clear();
                    filter2Field.Items.Clear();
                    

                    foreach (SPField spField in list.Fields)
                    {
                        if(!spField.Hidden)
                        {
                            checkedListBoxFields.Items.Add(spField.InternalName + " ( " + spField.Title + " )");
                            filter1Field.Items.Add(spField.InternalName + " ( " + spField.Title + " )");
                            filter2Field.Items.Add(spField.InternalName + " ( " + spField.Title + " )");
                        }
                    }
                }
            }
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            //verify all fields are set
            if(IsValid())
            {
                lblMessage.Text = "";
                 //check the selected list if a List or a Document Library
                using (SPSite site = new SPSite(_siteUrl))
                {
                    using (SPWeb web = site.OpenWeb(_webRelativeUrl))
                    {
                        SPList selectedList = web.Lists[_selectedListName];
                        List<string> selectedFieldsInternalName = new List<string>();

                        CheckedListBox.CheckedItemCollection collection = checkedListBoxFields.CheckedItems;

                        foreach (var item in collection)
                        {
                            int idx = item.ToString().IndexOf('(');
                            if(idx == -1)
                               selectedFieldsInternalName.Add(item.ToString().Trim());
                            selectedFieldsInternalName.Add(item.ToString().Substring(0,idx).Trim());
                        }

                        string destinationFolder = GenerateDestinationFolder(selectedList.Title);

                        string queryStr = GenerateQueryString(selectedList);

                        EventLog.WriteEntry("SharePoint Export List", queryStr, EventLogEntryType.Information);

                        SPListItemCollection items = null;
                        if (string.IsNullOrEmpty(queryStr))
                        {
                            items = selectedList.Items;
                        }
                        else
                        {
                            SPQuery query = new SPQuery();
                            query.ViewAttributes = "Scope='Recursive'";
                            query.Query = queryStr;
                            items = selectedList.GetItems(query);
                        }

                        if(selectedList is SPDocumentLibrary)
                        {

                            foreach (SPListItem listItem in items)
                            {
                                byte[] file = listItem.File.OpenBinary();

                                FileStream fileStream = new FileStream(string.Format("{0}\\{1}",destinationFolder, listItem.File.Name),FileMode.Create,FileAccess.ReadWrite);

                                fileStream.Write(file,0,file.Length);

                                fileStream.Close();      
                            }
                        }


                        StringBuilder sb = new StringBuilder();
                        string stringLine = string.Empty;
                        foreach (var sfin in selectedFieldsInternalName)
                        {
                            stringLine += sfin + ",";
                        }
                        sb.AppendLine(stringLine.TrimEnd(','));

                        foreach (SPListItem listItem in items)
                        {
                            string listValue = string.Empty;
                            foreach (var internalName in selectedFieldsInternalName)
                            {
                                string fieldValue = listItem[internalName] == null ? string.Empty : listItem[internalName].ToString();
                                listValue += fieldValue + ',';
                            }
                            sb.AppendLine(listValue.TrimEnd(','));
                        }
                        string metaDataFilePath = string.Format("{0}\\{1}_{2}.csv", destinationFolder,
                                                                selectedList.Title, DateTime.Now.ToString("yyyyMMdd"));
                        File.WriteAllText(metaDataFilePath,sb.ToString());
                        //export the selecetd list data
                    }
                }
                lblMessage.Text = "Success: Export Completed!";
            }
            else
            {
                lblMessage.Text = " Error: Validation Error.";

            }
        }

        private string GenerateQueryString(SPList listItem)
        {
            SPField field1 = null;
            SPField field2 = null;
            foreach (SPField spField in listItem.Fields)
            {
                if(_isFirstFilterSet)
                {
                    if(spField.InternalName.Equals(_filterOneFieldName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        field1 = spField;
                    }
                }
                if (_isSecondFilterSet)
                {
                    if (spField.InternalName.Equals(_filterTwoFieldName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        field2 = spField;
                    }
                }
                if(((_isFirstFilterSet && field1 != null ) || !_isFirstFilterSet) && ((_isSecondFilterSet && field2 != null ) || !_isFirstFilterSet))
                {
                    break;
                }
            }

            string orderQuery = string.Empty;

            if (!string.IsNullOrEmpty(_sortField))
            {
                orderQuery = string.Format("<OrderBy><FieldRef Name='{0}' {1} /></OrderBy>", _sortField,
                                           _ascending ? "" : "Ascending='False' ");
            }

            if(_isFirstFilterSet && _isSecondFilterSet)
            {
                string query = @"<Where>
                                    <{0}>
                                        <{1}>
                                            <FieldRef Name='{2}' />
                                            <Value Type='{3}'>{4}</Value>   
                                        </{1}>
                                        <{5}>
                                            <FieldRef Name='{6}' />
                                            <Value Type='{7}'>{8}</Value>   
                                        </{5}>
                                    </{0}>
                                    {9}
                                </Where>";
                return string.Format(query, 
                                    _filtersCondition, 
                                    _filterOneOp, 
                                    field1.InternalName, 
                                    field1.Type == SPFieldType.DateTime ? "DateOnly" : field1.Type.ToString(),
                                    _filterOneValue, 

                                    _filterTwoOp, 
                                    field2.InternalName, 
                                    field2.Type == SPFieldType.DateTime ? "DateOnly" : field2.Type.ToString(), 
                                    _filterTwoValue,
                                    
                                    orderQuery);
            }
            else if (_isFirstFilterSet)
            {
                string query = @"<Where>
                                    <{0}>
                                        <FieldRef Name='{1}' />
                                        <Value Type='{2}'>{3}</Value>   
                                    </{0}>
                                    {4}
                                </Where>";
                return string.Format(query, 
                                    _filterOneOp, 
                                    field1.InternalName, 
                                    field1.Type == SPFieldType.DateTime ? "DateOnly" : field1.Type.ToString(), 
                                    _filterOneValue,
                                    orderQuery);
            }
            else
            {
                return string.Empty;
            }
        }

        private string GenerateDestinationFolder(string listName)
        {
            string locationInput = txtLocation.Text.Trim();
            if (!locationInput.EndsWith("/"))
                locationInput += "/";
            string destinationFolder = locationInput + listName;
            if (!Directory.Exists(destinationFolder))
                Directory.CreateDirectory(destinationFolder);
            return destinationFolder;
        }

        private bool IsValid()
        {
            if (filter1Field.SelectedItem != null && filter1Field.SelectedItem.ToString().Trim().Length > 0)
                _isFirstFilterSet = true;
            else
                _isFirstFilterSet = false;
            if (filter2Field.SelectedItem != null && filter2Field.SelectedItem.ToString().Trim().Length > 0)
                _isSecondFilterSet = true;
            else
                _isSecondFilterSet = false;

            if(_isFirstFilterSet)
            {
                _filterOneFieldName = GetInternalName(filter1Field.SelectedItem.ToString());
                _filterOneOp = GetOpValue(filter1Condition.Text.Trim());
                _filterOneValue = filter1Text.Text.Trim();
            }else
            {
                _filterOneFieldName = string.Empty;
                _filterOneOp = string.Empty;
                _filterOneValue = string.Empty;
            }

            if (_isSecondFilterSet)
            {
                _filterTwoFieldName = GetInternalName(filter2Field.SelectedItem.ToString());
                _filterTwoOp = GetOpValue(filter2Condition.Text.Trim());
                _filterTwoValue = filter2Text.Text.Trim();
            }else
            {
                _filterTwoFieldName = string.Empty;
                _filterTwoOp = string.Empty;
                _filterTwoValue = string.Empty;
            }

            if (conditionsOp.SelectedItem != null)
                _filtersCondition = conditionsOp.SelectedItem.ToString().Trim();
            else
            {
                _filtersCondition = string.Empty;
            }

            if(comboBoxSortField.SelectedItem != null)
            {
                _sortField = comboBoxSortField.SelectedItem.ToString().Trim();
            }

            if(comboBoxSortOrder.SelectedItem != null)
            {
                _ascending = !comboBoxSortOrder.SelectedItem.ToString().Trim().Equals("Desc");
            }

            if (txtLocation.Text.Length > 0 && checkedListBoxFields.SelectedItems.Count > 0)
                return true;
            return false;
        }

        private string GetOpValue(string operation)
        {
            if(operation.Equals("Equal"))
                return "Eq";
            if(operation.Equals("Not Equal"))
                return "Neq";
            if(operation.Equals("Greater than"))
                return "Gt";
            if(operation.Equals("Greater than or Equal"))
                return "Geq";
            if(operation.Equals("Lower than"))
                return "Lt";
            if(operation.Equals("Lower than or Equal"))
                return "Leq";
            if(operation.Equals("Is null"))
                return "IsNull";
            if(operation.Equals("Is not Null"))
                return "IsNotNull";
            if(operation.Equals("Begins With"))
                return "BeginsWith";
            if (operation.Equals("Contains"))
                return "Contains";
            return string.Empty;
        }

        private string GetInternalName(string input)
        {
            int idx = input.IndexOf('(');
            if (idx == -1)
                return input.Trim();
            return input.Substring(0, idx).Trim();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ClearHideFitler();
        }

        private void ClearHideFitler()
        {
            filter2Condition.Visible = false;
            filter2Field.Visible = false;
            filter2Text.Visible = false;

            filter2Condition.SelectedItem = "";
            filter2Field.SelectedItem = "";
            filter2Text.Text = "";
        }

        private void ClearShowFitler()
        {
            filter2Condition.Visible = true;
            filter2Field.Visible = true;
            filter2Text.Visible = true;

            filter2Condition.SelectedItem = "";
            filter2Field.SelectedItem = "";
            filter2Text.Text = "";
        }

        private void conditionsOp_SelectedIndexChanged(object sender, EventArgs e)
        {
            string ops = conditionsOp.SelectedItem.ToString();
            if(string.IsNullOrEmpty(ops.Trim()) || ops.Trim().Equals("Filter"))
            {
                ClearHideFitler();
            }
            else
            {
                ClearShowFitler();
            }
        }
    }
}
